/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#include "Hardware.h"
#include <math/utl.h>
#include "Channel.h"


namespace liba {
namespace noise {
namespace hard {
namespace samsung {

Hardware::Hardware():
	exact_volume( 1 ),
	listener_front( 0, 0, 1 ),
	listener_up( 0, 1, 0),
	max_playing_channels( 4 )
{}

Hardware::~Hardware()
{
	for( ChannelStaticList::iterator it = static_channels.begin(); it != static_channels.end(); ++it )
	{
		(*it)->on_hardware_delete();
	}
}

hard::Channel * Hardware::create_static_channel( const Atom & channel_type, const filesystem::String & name)
{
	return new ChannelStatic(this, channel_type, name );
}
hard::Channel * Hardware::create_streaming_channel( const Atom & channel_type )
{
	//not implemented on android
	return 0;//new ChannelStreaming(this, channel_type, 5 );
}

void Hardware::life_cycle(double delta_time)
{
	ChannelStaticList::iterator it = playing_channels.begin();
	while( it != playing_channels.end() )
	{
		(*it)->life_cycle(delta_time, listener_position);
		if( (*it)->is_finished() )
			it = playing_channels.erase( it );
		else
			++it;
	}

	playing_channels.sort( ChannelStatic::SortPredicate );

	it = playing_channels.begin();
	for( int counter = 0; it != playing_channels.end(); ++counter, ++it )
	{
		if( counter < max_playing_channels && !(*it)->in_existance() )
		{
			(*it)->come_to_existance();
		}
		if( counter >= max_playing_channels && (*it)->in_existance() )
		{
			(*it)->begone();
		}
	}
}

bool Hardware::change_attribute(const Atom & name, const math::Vector3<float> & value)
{
	if( name == listener_position_name )
	{
		listener_position = value;
		return true;
	}
	if( name == listener_speed_name )
	{
		listener_speed = value;
		return true;
	}
	if( name == listener_up_name )
	{
		listener_up = value;
		return true;
	}
	if( name == listener_front_name )
	{
		listener_front = value;
		return true;
	}
	return hard::Hardware::change_attribute(name, value);
}

bool Hardware::change_attribute(const Atom & name, double value)
{
	if( name == global_volume_name )
	{
		exact_volume = math::clamp<double>( value, 0, 1);
		return true;
	}
	return hard::Hardware::change_attribute(name, value);
}

bool Hardware::change_attribute(const Atom & name, const Atom & value)
{
	if( name == listener_environment_name )
	{
		return true;
	}
	return hard::Hardware::change_attribute(name, value);
}

bool Hardware::get_attribute(const Atom & name, math::Vector3<float> * value)const
{
	return hard::Hardware::get_attribute(name, value);
}

bool Hardware::get_attribute(const Atom & name, double * value)const
{
	if( name == global_volume_name && value)
	{
		*value = exact_volume;
		return true;
	}
	return hard::Hardware::get_attribute(name, value);
}
} // namespace samsung
} // namespace hard
} // namespace noise
} // namespace liba
